from CDB import CDB
from Reorder_Buffer import Reorder_Buffer
from Resev_Station import ReservationStation
from Inst_queue import Instr_queue
from FP_Register import FPRegisters
from Execute_Unit import FPAdder, FPMultiplier
from Address_Unit import AddressUnit
from Memory_Unit import MemoryUnit
from Predict import BranchPredictor  # 导入分支预测器类

class Simulator:
    def __init__(self, instruct_file_path):
        self.fp_registers = FPRegisters()
        self.cdb = CDB()
        self.fp_adder = FPAdder(self.cdb)
        self.fp_multiplier = FPMultiplier(self.cdb)
        self.memory_unit = MemoryUnit(self.cdb)
        self.address_unit = AddressUnit(self.cdb)
        self.reorder_buffer = Reorder_Buffer(9, self.fp_registers, self.cdb)
        self.reservation_station = ReservationStation(self.cdb, self.fp_registers, self.fp_adder, self.fp_multiplier, self.memory_unit, self.address_unit, self.reorder_buffer)
        self.instr_queue = Instr_queue(instruct_file_path, self.reservation_station, self.reorder_buffer)
        self.branch_predictor = BranchPredictor()  # 初始化分支预测器
        self.clock = 0

    def runing(self):
        while self.instr_queue.has_more_instructions() or not self.reorder_buffer.is_empty():
            print(f"---------------------------Clock Cycle: {self.clock+1}---------------------------\n")
            self.cdb.clear()
            self.reorder_buffer.commit()
            self.reservation_station.execute_entries()
            self.reorder_buffer.check_cdb()
            self.reservation_station.update_operands()
            self.instr_queue.dispatch_instruction()
            
            # 更新分支预测器
            self.update_branch_predictions()

            self.clock += 1
            self.reorder_buffer.display()
            print()
            self.reservation_station.display()
            print()
            self.fp_registers.display_registers()
            print("\n\n")

            if self.clock > 100:
                break

    def update_branch_predictions(self):
        """
        更新分支预测器，处理分支指令的预测。
        """
        for entry in self.reservation_station.entries["Load"]:
            if entry["Op"] in ["BEQ", "BNE", "JUMP"]:  # 分支指令
                branch_address = entry["A"]  # 获取分支指令的地址
                predicted_taken = self.branch_predictor.predict(branch_address)  # 获取预测结果
                
                if predicted_taken:
                    print(f"Branch predicted to take: Address {branch_address}")
                else:
                    print(f"Branch predicted to not take: Address {branch_address}")

                # 更新分支预测器状态
                if entry["Op"] == "JUMP":
                    self.branch_predictor.update(branch_address, taken=True)
                elif entry["Op"] == "BEQ" and entry["Vj"] == entry["Vk"]:
                    self.branch_predictor.update(branch_address, taken=True)
                elif entry["Op"] == "BNE" and entry["Vj"] != entry["Vk"]:
                    self.branch_predictor.update(branch_address, taken=True)
                else:
                    self.branch_predictor.update(branch_address, taken=False)
